#include "../include/aj_sessioninfo.h"
#include <QFile>
#include <QFileInfo>
#include <QDate>
#include <QJsonDocument>
#include <QCryptographicHash>
#include "aj_globalData.h"

static QString replyTextFormat(
    "HTTP/1.1 %1 OK\r\n"
    "Content-Type: %2\r\n"
    "Content-Length: %3\r\n"
    "Access-Control-Allow-Origin: *\r\n"
    "Access-Control-Allow-Headers: Content-Type,X-Requested-With\r\n"
    "\r\n"
    "%4"
    );


SessionInfo::SessionInfo(std::shared_ptr<NETAPI::TcpSession> &session)
{
    this->Session_ = session;

    m_strIp = this->Session_->peerAddress().toString();//获取客户端的IP

    QStringList listIpStr = m_strIp.split(":");//ffff:192.168.1.104
    int countTmp = listIpStr.count();
    m_strStandardIp = listIpStr.at(countTmp - 1).split("%").at(0);


    connect(this->Session_.get(),&NETAPI::TcpSession::disconnected,this,&SessionInfo::SlotDisconnected);
    connect(this->Session_.get(),&NETAPI::TcpSession::SignalRead,this,&SessionInfo::SlotRead);
    //connect(this->Session_.get(),&NETAPI::TcpSession::connected,this,&SessionInfo::SignalConnected);

    headerAcceptedFinished_=false;
    contentAcceptedFinished_=false;

    m_overTimer = new QTimer(this);
    QObject::connect(m_overTimer, SIGNAL(timeout()), this, SLOT(SlotOverTimer()));
}

SessionInfo::~SessionInfo()
{
    delete m_overTimer;
    m_overTimer = nullptr;
    if (!this->Session_)
        return;
    disconnect(this->Session_.get(),&NETAPI::TcpSession::disconnected,this,&SessionInfo::SlotDisconnected);
    disconnect(this->Session_.get(),&NETAPI::TcpSession::SignalRead,this,&SessionInfo::SlotRead);
    //disconnect(this->Session_.get(),&NETAPI::TcpSession::connected,this,&SessionInfo::SignalConnected);
    this->Session_ = nullptr;
}

void SessionInfo::Connect(const QString &host, quint16 port)
{
    if (this->Session_)
        this->Session_->ConnectToServer(host, port);
}

void SessionInfo::Disconnect()
{
    if(m_overTimer->isActive())
    {
        m_overTimer->stop();
    }

    if (this->Session_)
        this->Session_->Disconnect();
}

void SessionInfo::Write(const char *buffer, int size)
{
    if (this->Session_)
        this->Session_->Write(buffer, size);
}


void SessionInfo::analyseBufferSetup1()
{
    if ( !headerAcceptedFinished_ )
    {
        forever
        {
            static QByteArray splitFlag( "\r\n" );

            auto splitFlagIndex = receiveBuffer_.indexOf( splitFlag );

            // 没有获取到分割标记，意味着数据不全
            if ( splitFlagIndex == -1 )
            {
                // 没有获取到 method 但是缓冲区内已经有了数据，这可能是一个无效的连接
                if ( requestMethod_.isEmpty() && ( receiveBuffer_.size() > 4 ) )
                {
                    //Disconnect();
                    return;
                }
                return;
            }

            // 如果未获取到 method 并且已经定位到了分割标记符，那么直接放弃这个连接
            if ( requestMethod_.isEmpty() && ( splitFlagIndex == 0 ) )
            {
                //Disconnect();
                return;
            }

            // 如果没有获取到 method 则先尝试分析 method
            if ( requestMethod_.isEmpty() )
            {
                auto requestLineDatas = receiveBuffer_.mid( 0, splitFlagIndex ).split( ' ' );
                receiveBuffer_.remove( 0, splitFlagIndex + 2 );

                if ( requestLineDatas.size() != 3 )
                {
                    //Disconnect();
                    return;
                }

                requestMethod_ = requestLineDatas.at( 0 );
                requestUrl_ = requestLineDatas.at( 1 );
                requestCrlf_ = requestLineDatas.at( 2 );

                if ( ( requestMethod_ != "GET" ) &&
                    ( requestMethod_ != "OPTIONS" ) &&
                    ( requestMethod_ != "POST" ) &&
                    ( requestMethod_ != "PUT" ) )
                {
                    //Disconnect();
                    return;
                }
            }
            else if ( splitFlagIndex == 0 )
            {
                receiveBuffer_.remove( 0, 2 );

                headerAcceptedFinished_ = true;

                if ( ( requestMethod_.toUpper() == "GET" ) ||
                    ( requestMethod_.toUpper() == "OPTIONS" ) ||
                    ( ( requestMethod_.toUpper() == "POST" ) && ( ( contentLength_ > 0 ) ? ( !receiveBuffer_.isEmpty() ) : ( true ) ) ) ||
                    ( ( requestMethod_.toUpper() == "PUT" ) && ( ( contentLength_ > 0 ) ? ( !receiveBuffer_.isEmpty() ) : ( true ) ) ) )
                {
                    this->analyseBufferSetup2();
                }
            }
            else
            {
                auto index = receiveBuffer_.indexOf( ':' );

                if ( index <= 0 )
                {
                    //Disconnect();
                    return;
                }

                auto headerData = receiveBuffer_.mid( 0, splitFlagIndex );
                receiveBuffer_.remove( 0, splitFlagIndex + 2 );

                const auto &&key = headerData.mid( 0, index );
                auto value = headerData.mid( index + 1 );

                if ( value.startsWith( ' ' ) )
                {
                    value.remove( 0, 1 );
                }

                requestHeader_[ key ] = value;

                if ( key.toLower() == "content-length" )
                {
                    contentLength_ = value.toLongLong();
                }
            }
        }
    }
    else
    {
        this->analyseBufferSetup2();
    }
}

bool SessionInfo::fkeyCheck(QString strMac,QString strTimestamp,QString strFkey)
{
    QString strPwdMd5;
    QByteArray ba, bb;
    QCryptographicHash md(QCryptographicHash::Md5);
    ba.append(strMac+strTimestamp + "4c3c0d0d7fbb39ae459");
    md.addData(ba);
    bb = md.result();

    strPwdMd5.append(bb.toHex().toLower());
    if(strFkey == strPwdMd5)
    {
        return true;
    }
    else
    {
        return false;
    }
}

void SessionInfo::analyseBufferSetup2()
{
    requestBody_ += receiveBuffer_;
    receiveBuffer_.clear();

    if ( ( contentLength_ != -1 ) && ( requestBody_.size() != contentLength_ ) )
    {
        return;
    }

    if ( contentAcceptedFinished_ )
    {
        return;
    }

    qDebug()<< QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss") << " : " << requestUrl_;
    if("/ajApi/getFaceFeature-url" == requestUrl_)
    {
        QByteArray content = QString::fromUtf8(requestBody_).remove("'\\").remove("\\").remove("'")
                            .toUtf8();
        qDebug()<< QString::fromUtf8(content);
        m_jsonObject = byteArrayToJson(content);

        int ret = fkeyCheck(m_jsonObject.value("mac").toString().replace("-",":"),m_jsonObject.value("timeMillis").toString(),m_jsonObject.value("fkey").toString());

        if(1)
        {
            m_strFilename = m_jsonObject.value("picUrl").toString();
            emit SignalProcessRequest(DOWNLOAD_PIC,QStringList()<<m_jsonObject.value("picUrl").toString());
        }
    }
    else if("/ajApi/notifyChange" == requestUrl_)
    {
        QByteArray content = QString::fromUtf8(requestBody_).remove("'\\").remove("\\").remove("'")
                            .toUtf8();
        qDebug()<< QString::fromUtf8(content);
        m_jsonObject = byteArrayToJson(content);

        int ret = fkeyCheck(m_jsonObject.value("mac").toString(),m_jsonObject.value("timestamp").toString(),m_jsonObject.value("fkey").toString());

        if(1)
        {
            //权限更新采用轮寻,此处直接返回,后台群发并无校验
            if(0x0A == ((m_jsonObject.value("cmd").toInt())&0xff))
            {
                emit SignalProcessRequest(UPDATE_INFO,QStringList()<<QString::number(m_jsonObject.value("cmd").toInt()));
                SlotUpdateInfoFinished(true,0x0A);
            }
            else if(0xCD == ((m_jsonObject.value("cmd").toInt())&0xff))//更新版本
            {
                qDebug()<<"get APK update order "<<QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
                emit SignalProcessRequest(UPDATE_VERSION,QStringList()<<QString::number(m_jsonObject.value("cmd").toInt())<<QString::number(m_jsonObject.value("operationRecordId").toInt()));
                SlotUpdateInfoFinished(true,0xCD);
            }
            else if(0xD1 == ((m_jsonObject.value("cmd").toInt())&0xff))//上传日志
            {
                qDebug()<<"upload log order "<<QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
                emit SignalProcessRequest(UPLOAD_LOG,QStringList()<<QString::number(m_jsonObject.value("cmd").toInt())<<QString::number(m_jsonObject.value("operationRecordId").toInt()));
                SlotUpdateInfoFinished(true,0xD1);
            }
            else
            {
                emit SignalProcessRequest(UPDATE_INFO,QStringList()<<QString::number(m_jsonObject.value("cmd").toInt()));
                SlotUpdateInfoFinished(true,((m_jsonObject.value("cmd").toInt())&0xff));
            }

        }
    }

    contentAcceptedFinished_ = true;
}

//void SessionInfo::SlotUpdateVersionStatus(int status)
//{
//    QString strFkey;
//    QByteArray ba, bb;
//    QCryptographicHash md(QCryptographicHash::Md5);
//    ba.append(g_macaddress_local+ g_timestamp + g_appKey);
//    md.addData(ba);
//    bb = md.result();
//    strFkey.append(bb.toHex().toLower());

//    qDebug()<<"reply:"<<m_jsonObject.value("cmd").toInt();
//    QJsonObject jsonObj;
//    jsonObj.insert("operationRecordId", m_lastOperationRecordId);
//    jsonObj.insert("operationStatus", QString::number(status));
//    jsonObj.insert("mac", g_macaddress_local);
//    jsonObj.insert("timestamp", g_timestamp);
//    jsonObj.insert("fkey", strFkey);
//    replyJsonObject(jsonObj,200);
//}

void SessionInfo::SlotUpdateInfoFinished(bool success,int cmd)
{
    if(0xCD == cmd)
    {
        qDebug()<<"reply:"<<m_jsonObject.value("cmd").toInt();
        QJsonObject jsonObj;
        jsonObj.insert("code", true == success?0:-1);
        jsonObj.insert("msg", true == success?"ok":"fail");
        //jsonObj.insert("cmd", m_jsonObject.value("cmd").toString()+QString("#%1").arg(qrand())+"#"+requestUrl_+"#"+QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss zzz"));
        jsonObj.insert("cmd", m_jsonObject.value("cmd").toInt());
        replyJsonObject(jsonObj,200);
    }
    else
    {
        qDebug()<<"reply:"<<m_jsonObject.value("cmd").toInt();
        QJsonObject jsonObj;
        jsonObj.insert("code", true == success?0:-1);
        jsonObj.insert("msg", true == success?"ok":"fail");
        //jsonObj.insert("cmd", m_jsonObject.value("cmd").toString()+QString("#%1").arg(qrand())+"#"+requestUrl_+"#"+QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss zzz"));
        jsonObj.insert("cmd", m_jsonObject.value("cmd").toInt());
        replyJsonObject(jsonObj,200);
        //Disconnect();
    }

}

void SessionInfo::SlotReceiveFaceFeature(QString strFilename,QByteArray faceFeture)
{
    if(!m_strFilename.contains(strFilename))
    {
        return;
    }

        QJsonObject jsonObj;
        jsonObj.insert("code", 0);
        jsonObj.insert("msg", "ok");
        jsonObj.insert("faceFeature", (QString)faceFeture.toBase64());
        //jsonObj.insert("userId", m_jsonObject.value("userId").toString()+QString("#%1").arg(qrand())+"#"+requestUrl_+"#"+QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss zzz"));
        jsonObj.insert("userId", m_jsonObject.value("userId").toString());
        replyJsonObject(jsonObj,200);
        //Disconnect();
}

QJsonObject SessionInfo::byteArrayToJson(const QByteArray &byteArray)
{
    // 确保QByteArray包含有效的UTF-8编码的JSON文本
    QJsonParseError parseError;
    QJsonDocument jsonDoc = QJsonDocument::fromJson(byteArray, &parseError);

    // 检查是否解析错误
    if (parseError.error != QJsonParseError::NoError) {
        // 解析错误，可以在这里处理错误，例如抛出异常或返回空对象
        return QJsonObject();
    }

    // 确认解析的文档是一个对象
    if (!jsonDoc.isObject()) {
        // 不是JSON对象，可以在这里处理错误，例如抛出异常或返回空对象
        return QJsonObject();
    }

    // 返回解析后的JSON对象
    return jsonDoc.object();
}

void SessionInfo::refreashCache()
{
    receiveBuffer_.clear();
    requestSourceIp_.clear();
    requestMethod_.clear();
    requestUrl_.clear();
    requestCrlf_.clear();
    requestBody_.clear();
    requestHeader_.clear();

    headerAcceptedFinished_  = false;
    contentAcceptedFinished_ = false;
    contentLength_           = -1;
}

void SessionInfo::SlotRead(const QByteArray &data, int size)
{
    m_overTimer->stop();

    refreashCache();
    receiveBuffer_.append(data);
    QByteArray kkk = receiveBuffer_;
    qDebug()<<"---------------------------------------------------------------------------------------------------"<<QString::fromStdString(kkk.toStdString());
    analyseBufferSetup1();

    m_overTimer->start(60*1000);//http请求过来后30秒超时断开，不管有没有处理成功
}

void SessionInfo::replyJsonObject(const QJsonObject &jsonObject, const int &httpStatusCode)
{
    QByteArray replyBuffer_ = QJsonDocument(jsonObject).toJson(QJsonDocument::Compact);
    qDebug()<<replyBuffer_<<"     "<<QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
    int replyBodySize_ = replyBuffer_.size();

    const auto &&buffer = replyTextFormat
                              .arg(
                                  QString::number(httpStatusCode),
                                  "application/json;charset=UTF-8",
                                  QString::number(replyBodySize_),
                                  QString(replyBuffer_))
                              .toUtf8();

    this->Write(buffer, buffer.size());
}
void SessionInfo::SlotDisconnected()
{
    //emit this->SignalDisconnect(m_strIp);//传出断开的客户端
    if (this->OnDisConnected)
        this->OnDisConnected(this);
}


void SessionInfo::SlotOverTimer()
{
    m_overTimer->stop();
    //超时后，断开连接，对象会被删除
    Disconnect();
}
